<?php

namespace Biz\service\advertisement\db;

use Biz\service\advertisement\interfaces\PositionCacheInterface;
use hhz\constant\redis\redisKeys;
use Hhz\Redis\newCache;
use Hhz\Redis\otherRedis;

abstract class Cache implements PositionCacheInterface
{

    const REDIS_TYPE_OTHER = 0;
    const REDIS_TYPE_NEW_CACHE = 1;
    protected static array $redisHandlerMap = [
        self::REDIS_TYPE_OTHER => otherRedis::class,
        self::REDIS_TYPE_NEW_CACHE => newCache::class,
    ];
    //自定义别名配置,外部调用需要聚集,方便管理
    protected static array $configs = [
         TaskCounterCache::class => [
             redisKeys::KEY_B_OTHER_AD_TASK_COUNTER,
             self::REDIS_TYPE_OTHER,
        ],
        PositionBaseInfoCache::class => [
            redisKeys::KEY_B_CACHE_AD_POSITION,
            self::REDIS_TYPE_NEW_CACHE,
        ],
        PositionCounterCache::class => [
            redisKeys::KEY_B_CACHE_AD_POSITION_COUNTER,
            self::REDIS_TYPE_NEW_CACHE,
        ],
    ];
    protected string $key = '';
    protected string $prefix = '';
    protected int $type = 0;
    protected array $errors = [];
    protected array $conf = [];

    private static array $instance = [];
    private  $redis;


    public static function cache($id)
    {
        $instance = self::getInstance();
        // 取缓存
        $cache = $instance->getCache($id);
        // 从方法中拿到需要的数据
        if ($instance->isEmpty($cache)) {
            // 获取数据
            $cache = $instance->getData($id);
            // 存缓存
            $instance->setCache($id, $cache);
        }
        return $cache;
    }

    public static function del($id = '')
    {
        return self::getInstance()->delCache($id);
    }

    public static function ttl($key = '')
    {
        return self::getInstance()->getTtl($key);
    }

    public static function ttlDesc($key = ''): string
    {
        $ttl = self::ttl($key);
        $desc = [
            -2 => 'not exist',
            -1 => 'has no associated expire',
        ];
        return $desc[$ttl] ?? $ttl . ' s';
    }

    public static function expire($key = '', $time = 0)
    {
        return self::getInstance()->setExpireTime($time, $key);
    }

    public static function expireAt($key = '', $time = 0)
    {
        return self::getInstance()->setExpireAt($time, $key);
    }

    /**
     */
    public function __construct(string $key)
    {
        $this->conf = self::$configs[$key] ?? [];
        if ($this->conf) {
            $this->prefix = $this->conf[0]; //定义的常量 key
            $this->type = $this->conf[1];
            $redisHandler = self::$redisHandlerMap[$this->type];
            $this->redis = new $redisHandler($this->prefix);
        }
    }


    public static function getInstance($module = '')
    {
        if ($module === '') $module = static::class;
        if (self::$instance[$module] === null) {
            self::$instance[$module] = new static($module);
        }
        return self::$instance[$module];
    }

    public function getRedis()
    {
        return $this->redis;
    }

    public function getOtherRedis(): otherRedis
    {
        return $this->redis;
    }

    public function getNewCacheRedis(): newCache
    {
        return $this->redis;
    }

    public function getCache($id = '')
    {
        if ($this->type == self::REDIS_TYPE_NEW_CACHE) {
            return $this->getNewCacheRedis()->getCache($id);
        }
        if ($this->type == self::REDIS_TYPE_OTHER) {
            $key = $this->getOtherRedis()->getFullKey($id);
            return $this->getOtherRedis()->get($key);
        }
        return null;
    }

    public function setCache($id, $data)
    {
        if ($this->type == self::REDIS_TYPE_NEW_CACHE) {
            return $this->getNewCacheRedis()->setCache($data, $id);
        }
        if ($this->type == self::REDIS_TYPE_OTHER) {
            $key = $this->getOtherRedis()->getFullKey($id);
            return $this->getOtherRedis()->set($key, $data);
        }
        return null;
    }

    public function isEmpty($cache): bool
    {
        return $cache === null;
    }

    public function delCache($id = '')
    {
        if ($this->type == self::REDIS_TYPE_NEW_CACHE) {
            return $this->getNewCacheRedis()->delCache($id);
        }
        if ($this->type == self::REDIS_TYPE_OTHER) {
            $key = $this->getOtherRedis()->getFullKey($id);
            return $this->getOtherRedis()->del($key);
        }
        return null;
    }

    public function setExpireTime($time = 0, $key = '')
    {
        if ($this->type == self::REDIS_TYPE_OTHER) {
            $key = $this->getOtherRedis()->getFullKey($key);
            return $this->getOtherRedis()->expire($key, $time);
        }
        return $this->getNewCacheRedis()->setExpireTime($time, $key);
    }

    public function setExpireAt($time = 0, $key = '')
    {
        return $this->getNewCacheRedis()->setExpireAt($time, $key);
    }
    public function getTtl($key = '')
    {
        if ($this->type == self::REDIS_TYPE_OTHER) {
            $key = $this->getOtherRedis()->getFullKey($key);
            return $this->getOtherRedis()->ttl($key);
        }
        return $this->getNewCacheRedis()->getTtl($key);
    }
}